package com.navinfo.tripanalysis.offline.util;

import com.navinfo.location.mileage.bean.MileageAndFuel;
import com.navinfo.platform.score.TripScoreService;
import com.navinfo.platform.score.pojo.ScoreWeight;
import com.navinfo.tripanalysis.common.arithmetic.common.*;
import com.navinfo.tripanalysis.common.pojo.*;
import com.navinfo.tripanalysis.common.util.ArithmeticUtils;
import com.navinfo.tripanalysis.offline.service.MilAndFuelService;
import com.navinfo.tripanalysis.offline.service.ServiceFactory;
import org.apache.commons.collections.CollectionUtils;
import org.apache.spark.broadcast.Broadcast;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
import java.util.Optional;

/**
 *
 * @author 沈东生
 */
public class TripStatisticUtils {
    private static final Logger logger = LoggerFactory.getLogger(TripStatisticUtils.class);

    /**
     * 中间变量的公共参数CommonData赋值
     * @param point
     * @param drivingData
     * @return
     */
    public static DrivingData assign(Point point, DrivingData drivingData) {
        CommonData commonData = drivingData.getCommonData();
        commonData.setGpsTime(point.getGpsTime());
        commonData.setLongitude(point.getLongitude());
        commonData.setLatitude(point.getLatitude());
        commonData.setOriginalLat(point.getOriginalLat());
        commonData.setOriginalLng(point.getOriginalLng());
        commonData.setHeight((int) point.getHeight());
        commonData.setGpsDirection(point.getDirection());
        commonData.setSpeedKmh((int) point.getSpeedKmh());
        commonData.setSpeedMs(BigDecimal.valueOf(point.getSpeedKmh()).divide(new BigDecimal("3.6"),  2, BigDecimal.ROUND_HALF_UP));
        commonData.setRotation(point.getRotation() );
        commonData.setBrake(point.getBrake()==1);
        commonData.setClutchSwitch(point.getClutchSwitch()==1 );
        commonData.setAcceleratorPosition(point.getAccPedalPos() );
        commonData.setEngineOutputTorque(point.getEngineOutputTorque() );
        commonData.setFuelConsumptionRate(BigDecimal.valueOf(point.getFuelConsumptionRate() ));
        commonData.setRealTimeOilConsumption(BigDecimal.valueOf(point.getRealTimeOilConsumption() ));

        if(ProtocolEnum.REALTIME.equals(point.getProtocol())){
            //大气温度(计算冷车运行用)
            if(point instanceof PointProtocol){
                commonData.setAtmosphericTem(((PointProtocol)point).getAtmosphericTem());
            }else if(point instanceof Point0F37){
                commonData.setAtmosphericTem(((Point0F37)point).getAtmosphericTem());
            }
        }
        else if(ProtocolEnum.LOCATION.equals(point.getProtocol())){
            if(point instanceof PointProtocol){
                assign0200Data(drivingData,(PointProtocol)point);
            }else if(point instanceof Point0200){
                assign0200Data(drivingData,(Point0200)point);
            }
        }

        //需要上个点属性计算的指标
        if (commonData.getLastGpsTime() > 0) {
            //与上个点的时间差（毫秒）
            long timeInterval = point.getGpsTime() - commonData.getLastGpsTime();
            commonData.setDffTime((int) timeInterval);

            //计算加速度
            try {
                commonData.setAcceleration( ArithmeticUtils.calculateAcceleratedSpeed(commonData.getLastSpeedMs().doubleValue(), commonData.getSpeedMs().doubleValue(), timeInterval));
            }catch (Exception ex){
                //如果计算加速度报错，则使用上一次的加速度
                logger.error(ex.getMessage(),ex);
            }
        }

        return drivingData;
    }

    /**
     * 将0200相关指标放到drivingData的commonData中
     * @param drivingData
     * @param pojo0200
     */
    public static void assign0200Data(DrivingData drivingData, Point0200 pojo0200) {
        CommonData data = drivingData.getCommonData();
        data.setAccStatus(pojo0200.getAccStatus() == 1);
        data.setCurve(pojo0200.getCurveStatus() == 1);
        data.setHandBrake(pojo0200.getHandBrakeStatus() == 1);
        data.setCruiseControl(pojo0200.getCruiseControl() == 1);
        data.setSharpTurning(pojo0200.getSharpTurningStatus() == 1);
        data.setSlideNeutral(pojo0200.getSlideNeutralStatus() == 1);
        data.setSlamTheAccelerator(pojo0200.getSlamAcceleratorStatus() == 1);
        data.setRapidAcceleration(pojo0200.getRapidAccelerationStatus() == 1);
        data.setRapidDeceleration(pojo0200.getRapidDecelerationStatus() == 1);

        data.setAmtLoad(pojo0200.getAmtLoad());
        data.setVecuLoad(pojo0200.getVecuLoad());
        data.setTotalOil(pojo0200.getTotalFuelCons());
        data.setWaterTemp(pojo0200.getCoolingWaterTem());
        data.setIntakeAirTem(pojo0200.getIntakeAirTem());
        data.setIntakePressure(pojo0200.getIntakePressure());
        data.setOilPercentage(pojo0200.getOilPercentage());
        if (data.isTripFirstNode()){
            data.setTripStartMeterMileage(pojo0200.getMeterMileage());
        }
    }

    /**
     * 将0200相关指标放到drivingData的commonData中
     * @param drivingData
     * @param pointProtocol
     */
    public static void assign0200Data(DrivingData drivingData, PointProtocol pointProtocol) {
        CommonData data = drivingData.getCommonData();
        data.setAccStatus(pointProtocol.getAccStatus() == 1);
        data.setCurve(pointProtocol.getCurveStatus() == 1);
        data.setHandBrake(pointProtocol.getHandBrakeStatus() == 1);
        data.setCruiseControl(pointProtocol.getCruiseControl() == 1);
        data.setSharpTurning(pointProtocol.getSharpTurningStatus() == 1);
        data.setSlideNeutral(pointProtocol.getSlideNeutralStatus() == 1);
        data.setSlamTheAccelerator(pointProtocol.getSlamAcceleratorStatus() == 1);
        data.setRapidAcceleration(pointProtocol.getRapidAccelerationStatus() == 1);
        data.setRapidDeceleration(pointProtocol.getRapidDecelerationStatus() == 1);

        data.setAmtLoad(pointProtocol.getAmtLoad());
        data.setVecuLoad(pointProtocol.getVecuLoad());
        data.setTotalOil(pointProtocol.getTotalFuelCons());
        data.setWaterTemp(pointProtocol.getCoolingWaterTem());
        data.setIntakeAirTem(pointProtocol.getIntakeAirTem());
        data.setIntakePressure(pointProtocol.getIntakePressure());
        data.setOilPercentage(pointProtocol.getOilPercentage());
        if (data.isTripFirstNode()){
            data.setTripStartMeterMileage(pointProtocol.getMeterMileage());
        }
    }

    /**
     * 根据0200的点，获取精准后的里程油耗
     * @param runningType
     * @param points
     * @return
     */
    public static MileageAndFuel calcMileageFuel(RunningTypeEnum runningType, List<Point0200> points){
        try {
            MilAndFuelService mileageAndFuel = ServiceFactory.createServiceImpl(runningType, MilAndFuelService.class);
            return mileageAndFuel.calcMileageFuel(points);
        } catch (IllegalAccessException | InstantiationException e) {
            e.printStackTrace();
        }

        return new MileageAndFuel();
    }

    public static MileageAndFuel calcMileageFuel(List<Point0200> points,MilAndFuelService mileageAndFuel){
        //MilAndFuelService mileageAndFuel = ServiceFactory.createServiceImpl(runningType, MilAndFuelService.class);
        return mileageAndFuel.calcMileageFuel(points);
    }

    /**
     * 计算行程开始和结束时的总里程、总油耗
     * @param statisticData
     * @param points
     */
    public static void calcStartEndMileageFuel(OuterStatisticData statisticData, List<Point0200> points) {
        if (CollectionUtils.isEmpty(points)) {
            return;
        }

        //获取行程开始的位置点
        Point0200 validPoint = null;
        for (Point0200 p : points) {
            if (p.getStandardFuelCons() > 0 && p.getStandardMileage() > 0) {
                validPoint = p;
                break;
            }
        }

        /* 设置行程开始结束里程油耗
        行程开始里程routeStartMileage：取0200第一个标准里程和标准油耗都>0点的标准里程StandardMileage
        行程开始油耗routeStartFuel：取0200第一个标准里程和标准油耗都>0点的标准油耗StandardFuelCons

        行程结束里程：行程开始里程routeStartMileage+行程内里程tripMileage
        行程结束油耗：行程开始油耗routeStartFuel+行程内里程tripFuel

        行程内里程tripMileage：（该行程根据0200的精准里程/当天所有行程的精准里程和）* 根据0200点精准的当天总里程
        行程内里程tripFuel：（该行程根据0200的精准油耗/当天所有行程的精准油耗和）* 根据0200点精准的当天总油耗
        */
        if (validPoint != null) {
            int startMileage = ArithmeticUtils.mileageKMToM(validPoint.getStandardMileage());
            int startFuel = ArithmeticUtils.fuelLToMl(validPoint.getStandardFuelCons());
            statisticData.setRouteStartMileage(startMileage);
            statisticData.setRouteStartFuel(startFuel);
            statisticData.setRouteEndMileage(startMileage + statisticData.getTripMileage());
            statisticData.setRouteEndFuel(startFuel + statisticData.getTripFuel());

            //cross_cities_detail加入行程开始里程油耗
            Optional.ofNullable(statisticData.getCrossCitiesDetail()).ifPresent(a ->{
                a.forEach(e -> {
                    e.setMileage(startMileage + e.getMileage() );
                    e.setFuel(startFuel + e.getFuel() );
                });
            });

        } else {
            logger.error("未找到有效的0200点，故不计算行程开始结束里程油耗...");
        }
    }

    /**
     * 计算行程打分
     * @param tripinfo
     * @param score
     */
    public static void calcTripScore(OuterStatisticData tripinfo, Broadcast<Map<String, ScoreWeight>> score){
        TripScoreService.init(score);
        Map<String,Integer> tripScoreMap = TripScoreService.calTripScoreMap(tripinfo, "", null);
        if(null!=tripScoreMap&&!tripScoreMap.isEmpty()){
            //综合得分
            tripinfo.setTotalScore(Optional.ofNullable(tripScoreMap.get("score")).orElse(0));
            //安全得分
            tripinfo.setSafeScore(Optional.ofNullable(tripScoreMap.get("safeScore")).orElse(0));
            //经济得分
            tripinfo.setEcoScore(Optional.ofNullable(tripScoreMap.get("ecoScore")).orElse(0));
        }
    }

    /**
     * 累加发动机数据流的缺项和异常项时长
     * @param drivingData
     * @param pointEngine
     */
    public static void assignEngineData(DrivingData drivingData, PointEngine pointEngine) {
        //非国六车辆，不统计发动机数据
        if (drivingData.getCn6BasicDataInfo() == null) {
            return;
        }
        //发动机数据统计信息
        EngineAggregatedData engineAggregatedData = drivingData.getEngineAggregatedData();
        long lastGpsTime = engineAggregatedData.getLastGpsTime();
        long gpsTime = pointEngine.getGpsTime();
        //如果数据排序不对，或者有相同时间的点，后边的点抛弃掉
        if (gpsTime <= lastGpsTime) {
            logger.info("===[cn6] 本次gps时间小于等于上个点的gps时间，不予处理! (本次:{},上次：{})===", gpsTime, lastGpsTime);
            return;
        }
        //发动机数据阈值范围信息
        Cn6EngineDataThresholdInfo engineDataThresholdInfo = drivingData.getEngineDataThresholdInfo();
        if (lastGpsTime == 0) {
            lastGpsTime = gpsTime;
        }
        //每个发动机数据流点需要记录点gpstime
        engineAggregatedData.setLastGpsTime(gpsTime);
        //发动机数据总点数
        engineAggregatedData.setEngineDataPoints(engineAggregatedData.getEngineDataPoints() + 1);
        //发动机是否有缺项和异常，每次直接用位运算，不做判断
        int engineDataMiss = engineAggregatedData.getExistEngineDataMiss();
        int engineDataAbnormal = engineAggregatedData.getExistEngineDataAbnormal();

        int timeDiff = (int)(gpsTime - lastGpsTime);

        //如果范围超出设置阈值34%，算作异常
        //超过阈值34%，两种情况，比最大值大出34%或者比最小值小出34%

        //车速
        int vehicleSpeed = pointEngine.getVehicleSpeed();
        engineAggregatedData.setSpeedTotal(engineAggregatedData.getSpeedTotal() + vehicleSpeed);
        if (vehicleSpeed > engineAggregatedData.getSpeedMax()) {
            engineAggregatedData.setSpeedMax(vehicleSpeed);
        }
        if (vehicleSpeed < engineAggregatedData.getSpeedMin()) {
            engineAggregatedData.setSpeedMin(vehicleSpeed);
        }
        if (vehicleSpeed == 0) {
            engineAggregatedData.setSpeedMissDuration(engineAggregatedData.getSpeedMissDuration() + timeDiff);
            engineAggregatedData.setSpeedMissPoints(engineAggregatedData.getSpeedMissPoints() + 1);
            engineDataMiss = engineDataMiss | (1 << EngineDataTerm.VEHICLE_SPEED.ordinal());
        } else if (new BigDecimal(vehicleSpeed).compareTo(engineDataThresholdInfo.getSpeedThresholdHigh()) > 0
                || new BigDecimal(vehicleSpeed).compareTo(engineDataThresholdInfo.getSpeedThresholdLow()) < 0) {
            engineAggregatedData.setSpeedAbnmDuration(engineAggregatedData.getSpeedAbnmDuration() + timeDiff);
            engineAggregatedData.setSpeedAbnmPoints(engineAggregatedData.getSpeedAbnmPoints() + 1);
            engineDataAbnormal = engineDataAbnormal | (1 << EngineDataTerm.VEHICLE_SPEED.ordinal());
        }
        //大气压力
        int barometricPressure = pointEngine.getBarometricPressure();
        engineAggregatedData.setBarometricPressureTotal(engineAggregatedData.getBarometricPressureTotal() + barometricPressure);
        if (barometricPressure > engineAggregatedData.getBarometricPressureMax()) {
            engineAggregatedData.setBarometricPressureMax(barometricPressure);
        }
        if (barometricPressure < engineAggregatedData.getBarometricPressureMin()) {
            engineAggregatedData.setBarometricPressureMin(barometricPressure);
        }
        if (barometricPressure == 0) {
            engineAggregatedData.setBarometricPressureMissDuration(engineAggregatedData.getBarometricPressureMissDuration() + timeDiff);
            engineAggregatedData.setBarometricPressureMissPoints(engineAggregatedData.getBarometricPressureMissPoints() + 1);
            engineDataMiss = engineDataMiss | (1 << EngineDataTerm.BAROMETRIC_PRESSURE.ordinal());
        } else if (new BigDecimal(barometricPressure).compareTo(engineDataThresholdInfo.getBarometricPressureThresholdHigh()) > 0
                || new BigDecimal(barometricPressure).compareTo(engineDataThresholdInfo.getBarometricPressureThresholdLow()) < 0) {
            engineAggregatedData.setBarometricPressureAbnmDuration(engineAggregatedData.getBarometricPressureAbnmDuration() + timeDiff);
            engineAggregatedData.setBarometricPressureAbnmPoints(engineAggregatedData.getBarometricPressureAbnmPoints() + 1);
            engineDataAbnormal = engineDataAbnormal | (1 << EngineDataTerm.BAROMETRIC_PRESSURE.ordinal());
        }
        //发动机净输出扭矩
        int engineOutputTorque = pointEngine.getEngineOutputTorque();
        engineAggregatedData.setOutputTorqueTotal(engineAggregatedData.getOutputTorqueTotal() + engineOutputTorque);
        if (engineOutputTorque > engineAggregatedData.getOutputTorqueMax()) {
            engineAggregatedData.setOutputTorqueMax(engineOutputTorque);
        }
        if (engineOutputTorque < engineAggregatedData.getOutputTorqueMin()) {
            engineAggregatedData.setOutputTorqueMin(engineOutputTorque);
        }
        if (engineOutputTorque == 0) {
            engineAggregatedData.setOutputTorqueMissDuration(engineAggregatedData.getOutputTorqueMissDuration() + timeDiff);
            engineAggregatedData.setOutputTorqueMissPoints(engineAggregatedData.getOutputTorqueMissPoints() + 1);
            engineDataMiss = engineDataMiss | (1 << EngineDataTerm.ENGINE_OUTPUT_TORQUE.ordinal());
        } else if (new BigDecimal(engineOutputTorque).compareTo(engineDataThresholdInfo.getEngineOutputTorqueThresholdHigh()) > 0
                || new BigDecimal(engineOutputTorque).compareTo(engineDataThresholdInfo.getEngineOutputTorqueThresholdLow()) < 0) {
            engineAggregatedData.setOutputTorqueAbnmDuration(engineAggregatedData.getOutputTorqueAbnmDuration() + timeDiff);
            engineAggregatedData.setOutputTorqueAbnmPoints(engineAggregatedData.getOutputTorqueAbnmPoints() + 1);
            engineDataAbnormal = engineDataAbnormal | (1 << EngineDataTerm.ENGINE_OUTPUT_TORQUE.ordinal());
        }
        //摩擦扭矩
        int frictionTorque = pointEngine.getFrictionTorque();
        engineAggregatedData.setFrictionTorqueTotal(engineAggregatedData.getFrictionTorqueTotal() + frictionTorque);
        if (frictionTorque > engineAggregatedData.getFrictionTorqueMax()) {
            engineAggregatedData.setFrictionTorqueMax(frictionTorque);
        }
        if (frictionTorque < engineAggregatedData.getFrictionTorqueMin()) {
            engineAggregatedData.setFrictionTorqueMin(frictionTorque);
        }
        if (frictionTorque == 0) {
            engineAggregatedData.setFrictionTorqueMissDuration(engineAggregatedData.getFrictionTorqueMissDuration() + timeDiff);
            engineAggregatedData.setFrictionTorqueMissPoints(engineAggregatedData.getFrictionTorqueMissPoints() + 1);
            engineDataMiss = engineDataMiss | (1 << EngineDataTerm.FRICTION_TORQUE.ordinal());
        } else if (new BigDecimal(frictionTorque).compareTo(engineDataThresholdInfo.getFrictionTorqueThresholdHigh()) > 0
                || new BigDecimal(frictionTorque).compareTo(engineDataThresholdInfo.getFrictionTorqueThresholdLow()) < 0) {
            engineAggregatedData.setFrictionTorqueAbnmDuration(engineAggregatedData.getFrictionTorqueAbnmDuration() + timeDiff);
            engineAggregatedData.setFrictionTorqueAbnmPoints(engineAggregatedData.getFrictionTorqueAbnmPoints() + 1);
            engineDataAbnormal = engineDataAbnormal | (1 << EngineDataTerm.FRICTION_TORQUE.ordinal());
        }
        //发动机转速
        int rotation = pointEngine.getRotation();
        engineAggregatedData.setRotationTotal(engineAggregatedData.getRotationTotal() + rotation);
        if (rotation > engineAggregatedData.getRotationMax()) {
            engineAggregatedData.setRotationMax(rotation);
        }
        if (rotation < engineAggregatedData.getRotationMin()) {
            engineAggregatedData.setRotationMin(rotation);
        }
        if (rotation == 0) {
            engineAggregatedData.setRotationMissDuration(engineAggregatedData.getRotationMissDuration() + timeDiff);
            engineAggregatedData.setRotationMissPoints(engineAggregatedData.getRotationMissPoints() + 1);
            engineDataMiss = engineDataMiss | (1 << EngineDataTerm.ROTATION.ordinal());
        } else if (new BigDecimal(rotation).compareTo(engineDataThresholdInfo.getRotationThresholdHigh()) > 0
                || new BigDecimal(rotation).compareTo(engineDataThresholdInfo.getRotationThresholdLow()) < 0) {
            engineAggregatedData.setRotationAbnmDuration(engineAggregatedData.getRotationAbnmDuration() + timeDiff);
            engineAggregatedData.setRotationAbnmPoints(engineAggregatedData.getRotationAbnmPoints() + 1);
            engineDataAbnormal = engineDataAbnormal | (1 << EngineDataTerm.ROTATION.ordinal());
        }
        //发动机燃料流量
        int fuelConsumptionRate = pointEngine.getFuelConsumption();
        engineAggregatedData.setFuelConsumptionTotal(engineAggregatedData.getFuelConsumptionTotal() + fuelConsumptionRate);
        if (fuelConsumptionRate > engineAggregatedData.getFuelConsumptionMax()) {
            engineAggregatedData.setFuelConsumptionMax(fuelConsumptionRate);
        }
        if (fuelConsumptionRate < engineAggregatedData.getFuelConsumptionMin()) {
            engineAggregatedData.setFuelConsumptionMin(fuelConsumptionRate);
        }
        if (fuelConsumptionRate == 0) {
            engineAggregatedData.setFuelConsumptionMissDuration(engineAggregatedData.getFuelConsumptionMissDuration() + timeDiff);
            engineAggregatedData.setFuelConsumptionMissPoints(engineAggregatedData.getFuelConsumptionMissPoints() + 1);
            engineDataMiss = engineDataMiss | (1 << EngineDataTerm.FUEL_CONSUMPTION_RATE.ordinal());
        } else if (new BigDecimal(fuelConsumptionRate).compareTo(engineDataThresholdInfo.getFuelConsumptionRateThresholdHigh()) > 0
                || new BigDecimal(fuelConsumptionRate).compareTo(engineDataThresholdInfo.getFuelConsumptionRateThresholdLow()) < 0) {
            engineAggregatedData.setFuelConsumptionAbnmDuration(engineAggregatedData.getFuelConsumptionAbnmDuration() + timeDiff);
            engineAggregatedData.setFuelConsumptionAbnmPoints(engineAggregatedData.getFuelConsumptionAbnmPoints() + 1);
            engineDataAbnormal = engineDataAbnormal | (1 << EngineDataTerm.FUEL_CONSUMPTION_RATE.ordinal());
        }
        //SCR上游NOx传感器输出值
        int scrUpNOx = pointEngine.getScrUpstreamNOxSensorOutput();
        engineAggregatedData.setScrUpNOxTotal(engineAggregatedData.getScrUpNOxTotal() + scrUpNOx);
        if (scrUpNOx > engineAggregatedData.getScrUpNOxMax()) {
            engineAggregatedData.setScrUpNOxMax(scrUpNOx);
        }
        if (scrUpNOx < engineAggregatedData.getScrUpNOxMin()) {
            engineAggregatedData.setScrUpNOxMin(scrUpNOx);
        }
        if (scrUpNOx == 0) {
            engineAggregatedData.setScrUpNOxMissDuration(engineAggregatedData.getScrUpNOxMissDuration() + timeDiff);
            engineAggregatedData.setScrUpNOxMissPoints(engineAggregatedData.getScrUpNOxMissPoints() + 1);
            engineDataMiss = engineDataMiss | (1 << EngineDataTerm.SCR_UPSTREAM_NOX_SENSOR_OUTPUT.ordinal());
        } else if (new BigDecimal(scrUpNOx).compareTo(engineDataThresholdInfo.getScrUpstreamNOxSensorOutputThresholdHigh()) > 0
                || new BigDecimal(scrUpNOx).compareTo(engineDataThresholdInfo.getScrUpstreamNOxSensorOutputThresholdLow()) < 0) {
            engineAggregatedData.setScrUpNOxAbnmDuration(engineAggregatedData.getScrUpNOxAbnmDuration() + timeDiff);
            engineAggregatedData.setScrUpNOxAbnmPoints(engineAggregatedData.getScrUpNOxAbnmPoints() + 1);
            engineDataAbnormal = engineDataAbnormal | (1 << EngineDataTerm.SCR_UPSTREAM_NOX_SENSOR_OUTPUT.ordinal());
        }
        //SCR下游NOx传感器输出值
        int scrDownNOx = pointEngine.getScrDownstreamNOxSensorOutput();
        engineAggregatedData.setScrDownNOxTotal(engineAggregatedData.getScrDownNOxTotal() + scrDownNOx);
        if (scrDownNOx > engineAggregatedData.getScrDownNOxMax()) {
            engineAggregatedData.setScrDownNOxMax(scrDownNOx);
        }
        if (scrDownNOx < engineAggregatedData.getScrDownNOxMin()) {
            engineAggregatedData.setScrDownNOxMin(scrDownNOx);
        }
        if (scrDownNOx == 0) {
            engineAggregatedData.setScrDownNOxMissDuration(engineAggregatedData.getScrDownNOxMissDuration() + timeDiff);
            engineAggregatedData.setScrDownNOxMissPoints(engineAggregatedData.getScrDownNOxMissPoints() + 1);
            engineDataMiss = engineDataMiss | (1 << EngineDataTerm.SCR_DOWNSTREAM_NOX_SENSOR_OUTPUT.ordinal());
        } else if (new BigDecimal(scrDownNOx).compareTo(engineDataThresholdInfo.getScrDownstreamNOxSensorOutputThresholdHigh()) > 0
                || new BigDecimal(scrDownNOx).compareTo(engineDataThresholdInfo.getScrDownstreamNOxSensorOutputThresholdLow()) < 0) {
            engineAggregatedData.setScrDownNOxAbnmDuration(engineAggregatedData.getScrDownNOxAbnmDuration() + timeDiff);
            engineAggregatedData.setScrDownNOxAbnmPoints(engineAggregatedData.getScrDownNOxAbnmPoints() + 1);
            engineDataAbnormal = engineDataAbnormal | (1 << EngineDataTerm.SCR_DOWNSTREAM_NOX_SENSOR_OUTPUT.ordinal());
        }
        //反应剂余量
        int reagentAllowance = pointEngine.getReagentAllowance();
        engineAggregatedData.setReagentAllowanceTotal(engineAggregatedData.getReagentAllowanceTotal() + reagentAllowance);
        if (reagentAllowance > engineAggregatedData.getReagentAllowanceMax()) {
            engineAggregatedData.setReagentAllowanceMax(reagentAllowance);
        }
        if (reagentAllowance < engineAggregatedData.getReagentAllowanceMin()) {
            engineAggregatedData.setReagentAllowanceMin(reagentAllowance);
        }
        if (reagentAllowance == 0) {
            engineAggregatedData.setReagentAllowanceMissDuration(engineAggregatedData.getReagentAllowanceMissDuration() + timeDiff);
            engineAggregatedData.setReagentAllowanceMissPoints(engineAggregatedData.getReagentAllowanceMissPoints() + 1);
            engineDataMiss = engineDataMiss | (1 << EngineDataTerm.REAGENT_ALLOWANCE.ordinal());
        } else if (new BigDecimal(reagentAllowance).compareTo(engineDataThresholdInfo.getReagentAllowanceThresholdHigh()) > 0
                || new BigDecimal(reagentAllowance).compareTo(engineDataThresholdInfo.getReagentAllowanceThresholdLow()) < 0) {
            engineAggregatedData.setReagentAllowanceAbnmDuration(engineAggregatedData.getReagentAllowanceAbnmDuration() + timeDiff);
            engineAggregatedData.setReagentAllowanceAbnmPoints(engineAggregatedData.getReagentAllowanceAbnmPoints() + 1);
            engineDataAbnormal = engineDataAbnormal | (1 << EngineDataTerm.REAGENT_ALLOWANCE.ordinal());
        }
        //进气量
        int airInflow = pointEngine.getAirInflow();
        engineAggregatedData.setAirInflowTotal(engineAggregatedData.getAirInflowTotal() + airInflow);
        if (airInflow > engineAggregatedData.getAirInflowMax()) {
            engineAggregatedData.setAirInflowMax(airInflow);
        }
        if (airInflow < engineAggregatedData.getAirInflowMin()) {
            engineAggregatedData.setAirInflowMin(airInflow);
        }
        if (airInflow == 0) {
            engineAggregatedData.setAirInflowMissDuration(engineAggregatedData.getAirInflowMissDuration() + timeDiff);
            engineAggregatedData.setAirInflowMissPoints(engineAggregatedData.getAirInflowMissPoints() + 1);
            engineDataMiss = engineDataMiss | (1 << EngineDataTerm.AIR_INFLOW.ordinal());
        } else if (new BigDecimal(airInflow).compareTo(engineDataThresholdInfo.getAirInflowThresholdHigh()) > 0
                || new BigDecimal(airInflow).compareTo(engineDataThresholdInfo.getAirInflowThresholdLow()) < 0) {
            engineAggregatedData.setAirInflowAbnmDuration(engineAggregatedData.getAirInflowAbnmDuration() + timeDiff);
            engineAggregatedData.setAirInflowAbnmPoints(engineAggregatedData.getAirInflowAbnmPoints() + 1);
            engineDataAbnormal = engineDataAbnormal | (1 << EngineDataTerm.AIR_INFLOW.ordinal());
        }
        //SCR入口温度
        int scrInletTemperature = pointEngine.getScrInletTemperature();
        engineAggregatedData.setScrInTotal(engineAggregatedData.getScrInTotal() + scrInletTemperature);
        if (scrInletTemperature > engineAggregatedData.getScrInMax()) {
            engineAggregatedData.setScrInMax(scrInletTemperature);
        }
        if (scrInletTemperature < engineAggregatedData.getScrInMin()) {
            engineAggregatedData.setScrInMin(scrInletTemperature);
        }
        if (scrInletTemperature == 0) {
            engineAggregatedData.setScrInMissDuration(engineAggregatedData.getScrInMissDuration() + timeDiff);
            engineAggregatedData.setScrInMissPoints(engineAggregatedData.getScrInMissPoints() + 1);
            engineDataMiss = engineDataMiss | (1 << EngineDataTerm.SCR_INLET_TEMPERATURE.ordinal());
        } else if (new BigDecimal(scrInletTemperature).compareTo(engineDataThresholdInfo.getScrInletTemperatureThresholdHigh()) > 0
                || new BigDecimal(scrInletTemperature).compareTo(engineDataThresholdInfo.getScrInletTemperatureThresholdLow()) < 0) {
            engineAggregatedData.setScrInAbnmDuration(engineAggregatedData.getScrInAbnmDuration() + timeDiff);
            engineAggregatedData.setScrInAbnmPoints(engineAggregatedData.getScrInAbnmPoints() + 1);
            engineDataAbnormal = engineDataAbnormal | (1 << EngineDataTerm.SCR_INLET_TEMPERATURE.ordinal());
        }
        //SCR出口温度
        int scrOutletTemperature = pointEngine.getScrOutletTemperature();
        engineAggregatedData.setScrOutTotal(engineAggregatedData.getScrOutTotal() + scrOutletTemperature);
        if (scrOutletTemperature > engineAggregatedData.getScrOutMax()) {
            engineAggregatedData.setScrOutMax(scrOutletTemperature);
        }
        if (scrOutletTemperature < engineAggregatedData.getScrOutMin()) {
            engineAggregatedData.setScrOutMin(scrOutletTemperature);
        }
        if (scrOutletTemperature == 0) {
            engineAggregatedData.setScrOutMissDuration(engineAggregatedData.getScrOutMissDuration() + timeDiff);
            engineAggregatedData.setScrOutMissPoints(engineAggregatedData.getScrOutMissPoints() + 1);
            engineDataMiss = engineDataMiss | (1 << EngineDataTerm.SCR_OUTLET_TEMPERATURE.ordinal());
        } else if (new BigDecimal(scrOutletTemperature).compareTo(engineDataThresholdInfo.getScrOutletTemperatureThresholdHigh()) > 0
                || new BigDecimal(scrOutletTemperature).compareTo(engineDataThresholdInfo.getScrOutletTemperatureThresholdLow()) < 0) {
            engineAggregatedData.setScrOutAbnmDuration(engineAggregatedData.getScrOutAbnmDuration() + timeDiff);
            engineAggregatedData.setScrOutAbnmPoints(engineAggregatedData.getScrOutAbnmPoints() + 1);
            engineDataAbnormal = engineDataAbnormal | (1 << EngineDataTerm.SCR_OUTLET_TEMPERATURE.ordinal());
        }
        //DPF压差
        int dpfDropoutVoltage = pointEngine.getDpfDropoutVoltage();
        engineAggregatedData.setDropoutVoltageTotal(engineAggregatedData.getDropoutVoltageTotal() + dpfDropoutVoltage);
        if (dpfDropoutVoltage > engineAggregatedData.getDropoutVoltageMax()) {
            engineAggregatedData.setDropoutVoltageMax(dpfDropoutVoltage);
        }
        if (dpfDropoutVoltage < engineAggregatedData.getDropoutVoltageMin()) {
            engineAggregatedData.setDropoutVoltageMin(dpfDropoutVoltage);
        }
        if (dpfDropoutVoltage == 0) {
            engineAggregatedData.setDropoutVoltageMissDuration(engineAggregatedData.getDropoutVoltageMissDuration() + timeDiff);
            engineAggregatedData.setDropoutVoltageMissPoints(engineAggregatedData.getDropoutVoltageMissPoints() + 1);
            engineDataMiss = engineDataMiss | (1 << EngineDataTerm.DPF_DROPOUT_VOLTAGE.ordinal());
        } else if (new BigDecimal(dpfDropoutVoltage).compareTo(engineDataThresholdInfo.getDpfDropoutVoltageThresholdHigh()) > 0
                || new BigDecimal(dpfDropoutVoltage).compareTo(engineDataThresholdInfo.getDpfDropoutVoltageThresholdLow()) < 0) {
            engineAggregatedData.setDropoutVoltageAbnmDuration(engineAggregatedData.getDropoutVoltageAbnmDuration() + timeDiff);
            engineAggregatedData.setDropoutVoltageAbnmPoints(engineAggregatedData.getDropoutVoltageAbnmPoints() + 1);
            engineDataAbnormal = engineDataAbnormal | (1 << EngineDataTerm.DPF_DROPOUT_VOLTAGE.ordinal());
        }
        //发动机冷却液温度
        int engineCoolantTemperature = pointEngine.getEngineCoolantTemperature();
        engineAggregatedData.setCoolantTemperatureTotal(engineAggregatedData.getCoolantTemperatureTotal() + engineCoolantTemperature);
        if (engineCoolantTemperature > engineAggregatedData.getCoolantTemperatureMax()) {
            engineAggregatedData.setCoolantTemperatureMax(engineCoolantTemperature);
        }
        if (engineCoolantTemperature < engineAggregatedData.getCoolantTemperatureMin()) {
            engineAggregatedData.setCoolantTemperatureMin(engineCoolantTemperature);
        }
        if (engineCoolantTemperature == 0) {
            engineAggregatedData.setCoolantTemperatureMissDuration(engineAggregatedData.getCoolantTemperatureMissDuration() + timeDiff);
            engineAggregatedData.setCoolantTemperatureMissPoints(engineAggregatedData.getCoolantTemperatureMissPoints() + 1);
            engineDataMiss = engineDataMiss | (1 << EngineDataTerm.ENGINE_COOLANT_TEMPERATURE.ordinal());
        } else if (new BigDecimal(engineCoolantTemperature).compareTo(engineDataThresholdInfo.getEngineCoolantTemperatureThresholdHigh()) > 0
                || new BigDecimal(engineCoolantTemperature).compareTo(engineDataThresholdInfo.getEngineCoolantTemperatureThresholdLow()) < 0) {
            engineAggregatedData.setCoolantTemperatureAbnmDuration(engineAggregatedData.getCoolantTemperatureAbnmDuration() + timeDiff);
            engineAggregatedData.setCoolantTemperatureAbnmPoints(engineAggregatedData.getCoolantTemperatureAbnmPoints() + 1);
            engineDataAbnormal = engineDataAbnormal | (1 << EngineDataTerm.ENGINE_COOLANT_TEMPERATURE.ordinal());
        }
        //油箱液位
        int tankLevel = pointEngine.getTankLevel();
        engineAggregatedData.setTankLevelTotal(engineAggregatedData.getTankLevelTotal() + tankLevel);
        if (tankLevel > engineAggregatedData.getTankLevelMax()) {
            engineAggregatedData.setTankLevelMax(tankLevel);
        }
        if (tankLevel < engineAggregatedData.getTankLevelMin()) {
            engineAggregatedData.setTankLevelMin(tankLevel);
        }
        if (tankLevel == 0) {
            engineAggregatedData.setTankLevelMissDuration(engineAggregatedData.getTankLevelMissDuration() + timeDiff);
            engineAggregatedData.setTankLevelMissPoints(engineAggregatedData.getTankLevelMissPoints() + 1);
            engineDataMiss = engineDataMiss | (1 << EngineDataTerm.TANK_LEVEL.ordinal());
        } else if (new BigDecimal(tankLevel).compareTo(engineDataThresholdInfo.getTankLevelThresholdHigh()) > 0
                || new BigDecimal(tankLevel).compareTo(engineDataThresholdInfo.getTankLevelThresholdLow()) < 0) {
            engineAggregatedData.setTankLevelAbnmDuration(engineAggregatedData.getTankLevelAbnmDuration() + timeDiff);
            engineAggregatedData.setTankLevelAbnmPoints(engineAggregatedData.getTankLevelAbnmPoints() + 1);
            engineDataAbnormal = engineDataAbnormal | (1 << EngineDataTerm.TANK_LEVEL.ordinal());
        }

        //三元催化器下游NOX传感器输出
        int ternaryDownNOxOutput = pointEngine.getTernaryCatalystDownstreamNOxSensorOutput();
        engineAggregatedData.setTernaryDownNOxOutputTotal(engineAggregatedData.getTernaryDownNOxOutputTotal() + ternaryDownNOxOutput);
        if (ternaryDownNOxOutput > engineAggregatedData.getTernaryDownNOxOutputMax()) {
            engineAggregatedData.setTernaryDownNOxOutputMax(ternaryDownNOxOutput);
        }
        if (ternaryDownNOxOutput < engineAggregatedData.getTernaryDownNOxOutputMin()) {
            engineAggregatedData.setTernaryDownNOxOutputMin(ternaryDownNOxOutput);
        }
        if (ternaryDownNOxOutput == 0) {
            engineAggregatedData.setTernaryDownNOxOutputMissDuration(engineAggregatedData.getTernaryDownNOxOutputMissDuration() + timeDiff);
            engineAggregatedData.setTernaryDownNOxOutputMissPoints(engineAggregatedData.getTernaryDownNOxOutputMissPoints() + 1);
            engineDataMiss = engineDataMiss | (1 << EngineDataTerm.TERNARY_DOWN_NOX_OUTPUT.ordinal());
        }
        //三元催化器上游氧传感器输出
        int ternaryUpO2Output = pointEngine.getTernaryCatalystUpstreamO2SensorOutput();
        engineAggregatedData.setTernaryUpO2OutputTotal(engineAggregatedData.getTernaryUpO2OutputTotal() + ternaryUpO2Output);
        if (ternaryUpO2Output > engineAggregatedData.getTernaryUpO2OutputMax()) {
            engineAggregatedData.setTernaryUpO2OutputMax(ternaryUpO2Output);      ;
        }
        if (ternaryUpO2Output < engineAggregatedData.getTernaryUpO2OutputMin()) {
            engineAggregatedData.setTernaryUpO2OutputMin(ternaryUpO2Output);
        }
        if (ternaryUpO2Output == 0) {
            engineAggregatedData.setTernaryUpO2OutputMissDuration(engineAggregatedData.getTernaryUpO2OutputMissDuration() + timeDiff);
            engineAggregatedData.setTernaryUpO2OutputMissPoints(engineAggregatedData.getTernaryUpO2OutputMissPoints() + 1);
            engineDataMiss = engineDataMiss | (1 << EngineDataTerm.TERNARY_UP_O2_OUTPUT.ordinal());
        } else if (new BigDecimal(ternaryUpO2Output).compareTo(engineDataThresholdInfo.getTernaryUpO2OutputThresholdHigh()) > 0
                || new BigDecimal(ternaryUpO2Output).compareTo(engineDataThresholdInfo.getTernaryUpO2OutputThresholdLow()) < 0) {
            engineAggregatedData.setTernaryUpO2OutputAbnmDuration(engineAggregatedData.getTernaryUpO2OutputAbnmDuration() + timeDiff);
            engineAggregatedData.setTernaryUpO2OutputAbnmPoints(engineAggregatedData.getTernaryUpO2OutputAbnmPoints() + 1);
            engineDataAbnormal = engineDataAbnormal | (1 << EngineDataTerm.TERNARY_UP_O2_OUTPUT.ordinal());
        }

        //三元催化器下游氧传感器输出
        int ternaryDownO2Output = pointEngine.getTernaryCatalystDownstreamO2SensorOutput();
        engineAggregatedData.setTernaryDownO2OutputTotal(engineAggregatedData.getTernaryDownO2OutputTotal() + ternaryDownO2Output);
        if (ternaryDownO2Output > engineAggregatedData.getTernaryDownO2OutputMax()) {
            engineAggregatedData.setTernaryDownO2OutputMax(ternaryDownO2Output);      ;
        }
        if (ternaryDownO2Output < engineAggregatedData.getTernaryDownO2OutputMin()) {
            engineAggregatedData.setTernaryDownO2OutputMin(ternaryDownO2Output);
        }
        if (ternaryDownO2Output == 0) {
            engineAggregatedData.setTernaryDownO2OutputMissDuration(engineAggregatedData.getTernaryDownO2OutputMissDuration() + timeDiff);
            engineAggregatedData.setTernaryDownO2OutputMissPoints(engineAggregatedData.getTernaryDownO2OutputMissPoints() + 1);
            engineDataMiss = engineDataMiss | (1 << EngineDataTerm.TERNARY_DOWN_O2_OUTPUT.ordinal());
        } else if (new BigDecimal(ternaryDownO2Output).compareTo(engineDataThresholdInfo.getTernaryDownO2OutputThresholdHigh()) > 0
                || new BigDecimal(ternaryDownO2Output).compareTo(engineDataThresholdInfo.getTernaryDownO2OutputThresholdLow()) < 0) {
            engineAggregatedData.setTernaryDownO2OutputAbnmDuration(engineAggregatedData.getTernaryDownO2OutputAbnmDuration() + timeDiff);
            engineAggregatedData.setTernaryDownO2OutputAbnmPoints(engineAggregatedData.getTernaryDownO2OutputAbnmPoints() + 1);
            engineDataAbnormal = engineDataAbnormal | (1 << EngineDataTerm.TERNARY_DOWN_O2_OUTPUT.ordinal());
        }
        //三元催化器温度传感器输出
        int ternaryTemperatureOutput = pointEngine.getTernaryCatalyticConverterTemperature();
        engineAggregatedData.setTernaryTemperatureOutputTotal(engineAggregatedData.getTernaryTemperatureOutputTotal() + ternaryTemperatureOutput);
        if (ternaryTemperatureOutput > engineAggregatedData.getTernaryTemperatureOutputMax()) {
            engineAggregatedData.setTernaryTemperatureOutputMax(ternaryTemperatureOutput);      ;
        }
        if (ternaryTemperatureOutput < engineAggregatedData.getTernaryTemperatureOutputMin()) {
            engineAggregatedData.setTernaryTemperatureOutputMin(ternaryTemperatureOutput);
        }
        // 三元催化器传感器温度 缺项点
        if (ternaryTemperatureOutput == 0) {
            engineAggregatedData.setTernaryTemperatureOutputMissDuration(engineAggregatedData.getTernaryTemperatureOutputMissDuration() + timeDiff);
            engineAggregatedData.setTernaryTemperatureOutputMissPoints(engineAggregatedData.getTernaryTemperatureOutputMissPoints() + 1);
            engineDataMiss = engineDataMiss | (1 << EngineDataTerm.TEMPERATURE_OUTPUT.ordinal());
            // 三元催化器传感器温度 异常点
        }else if (new BigDecimal(ternaryTemperatureOutput).compareTo(engineDataThresholdInfo.getTemperatureOutputThresholdHigh()) > 0
                || new BigDecimal(ternaryTemperatureOutput).compareTo(engineDataThresholdInfo.getTemperatureOutputThresholdLow()) < 0) {
            engineAggregatedData.setTernaryTemperatureOutputAbnmDuration(engineAggregatedData.getTernaryTemperatureOutputAbnmDuration() + timeDiff);
            engineAggregatedData.setTernaryTemperatureOutputAbnmPoints(engineAggregatedData.getTernaryTemperatureOutputAbnmPoints() + 1);
            engineDataAbnormal = engineDataAbnormal | (1 << EngineDataTerm.TEMPERATURE_OUTPUT.ordinal());
        }
        //定位状态，经度，纬度，累计里程，只统计缺项，不统计异常项
        //定位状态值为1时，为无效定位，此处将其算作缺项
        int positioningState = pointEngine.getPositioningState();
        if (positioningState == 1) {
            engineAggregatedData.setPositioningStateMissDuration(engineAggregatedData.getPositioningStateMissDuration() + timeDiff);
            engineAggregatedData.setPositioningStateMissPoints(engineAggregatedData.getPositioningStateMissPoints() + 1);
            engineDataMiss = engineDataMiss | (1 << EngineDataTerm.POSITIONING_STATE.ordinal());
        }

        int longitude = pointEngine.getLongitude();
        if (longitude == 0) {
            engineAggregatedData.setLongitudeMissDuration(engineAggregatedData.getLongitudeMissDuration() + timeDiff);
            engineAggregatedData.setLongitudeMissPoints(engineAggregatedData.getLongitudeMissPoints() + 1);
            engineDataMiss = engineDataMiss | (1 << EngineDataTerm.LONGITUDE.ordinal());
        }

        int latitude = pointEngine.getLatitude();
        if (latitude == 0) {
            engineAggregatedData.setLatitudeMissDuration(engineAggregatedData.getLatitudeMissDuration() + timeDiff);
            engineAggregatedData.setLatitudeMissPoints(engineAggregatedData.getLatitudeMissPoints() + 1);
            engineDataMiss = engineDataMiss | (1 << EngineDataTerm.LATITUDE.ordinal());
        }

        long mileage = pointEngine.getMileage();
        if (mileage == 0) {
            engineAggregatedData.setMileageMissDuration(engineAggregatedData.getMileageMissDuration() + timeDiff);
            engineAggregatedData.setMileageMissPoints(engineAggregatedData.getMileageMissPoints() + 1);
            engineDataMiss = engineDataMiss | (1 << EngineDataTerm.MILEAGE.ordinal());
        }
        //设置有哪些项有缺项
        engineAggregatedData.setExistEngineDataMiss(engineDataMiss);
        //设置有哪些项有异常
        engineAggregatedData.setExistEngineDataAbnormal(engineDataAbnormal);
    }

}
